
#include "Config.h"
#include "reg.h"
#include "typedefs.h"
#include "Printf.h"
#include "I2C.h"
#include "CPU.h"
#include "Global.h"
#include "data\data.c"
#include "dv_api.h"


CODE BYTE* CODE Table88_Inport[MAXINPORT]={
	Table_INPORT_CVBS0,
	Table_INPORT_CVBS1,
	Table_INPORT_CVBS2,
	Table_INPORT_CVBS3,
	Table_INPORT_YC,
	Table_INPORT_DTV1,
	Table_INPORT_DTV2_BT656,
	Table_INPORT_ARGB_HV,
	Table_INPORT_ARGB_SOG,
	Table_INPORT_EXCVBS0,
	Table_INPORT_EXYC
};

CODE BYTE* CODE Table88_Sig_FMT[MAX_SIG_FMT]={
	Table_SIGFMT_NTSC,
	Table_SIGFMT_PAL,
	Table_SIGFMT_YUV480i,
	Table_SIGFMT_YUV576i,
	Table_SIGFMT_YUV480p,
	Table_SIGFMT_YUV576p,
	Table_SIGFMT_SVGA60,
	Table_SIGFMT_DTV480i,
	Table_SIGFMT_DTV576i
};

CODE BYTE* CODE Table88_Outport[MAXOUTPORT]={
	Table_OUTPORT_MAIN,
	Table_OUTPORT_PIP0,
	Table_OUTPORT_PIP1
};

CODE BYTE* CODE Table88_Scaler[MAX_SIG_FMT][MAX_DISP_MODE]={
	{Table_NTSC_M_FULL,    Table_NTSC_M_HALF,    Table_NTSC_S0_SMALL,    Table_NTSC_S0_MIDDLE,    Table_NTSC_S0_LARGE,    Table_NTSC_S0_POP,    Table_DTV2480I_S0_DUAL,Table_YUV480I_S1_DUAL},
	{Table_PAL_M_FULL,     Table_PAL_M_HALF,     Table_PAL_S0_SMALL,     Table_PAL_S0_MIDDLE,     Table_PAL_S0_LARGE,     Table_PAL_S0_POP,     Table_DTV2480I_S0_DUAL,Table_YUV480I_S1_DUAL},
	{Table_YUV480I_M_FULL, Table_YUV480I_M_HALF, Table_YUV480I_S0_SMALL, Table_YUV480I_S0_MIDDLE, Table_YUV480I_S0_LARGE, Table_YUV480I_S0_POP, Table_DTV2480I_S0_DUAL,Table_YUV480I_S1_DUAL},
	{Table_YUV576I_M_FULL, Table_YUV576I_M_HALF, Table_YUV576I_S0_SMALL, Table_YUV576I_S0_MIDDLE, Table_YUV576I_S0_LARGE, Table_YUV576I_S0_POP, Table_DTV2480I_S0_DUAL,Table_YUV576I_S1_DUAL},
	{Table_YUV480P_M_FULL, Table_YUV480P_M_HALF, Table_YUV480P_S0_SMALL, Table_YUV480P_S0_MIDDLE, Table_YUV480P_S0_LARGE, Table_YUV480P_S0_POP, Table_DTV2480I_S0_DUAL,Table_YUV480I_S1_DUAL},
	{Table_YUV576P_M_FULL, Table_YUV576P_M_HALF, Table_YUV576P_S0_SMALL, Table_YUV576P_S0_MIDDLE, Table_YUV576P_S0_LARGE, Table_YUV576P_S0_POP, Table_DTV2480I_S0_DUAL,Table_YUV480I_S1_DUAL},
	{Table_SVGA60_M_FULL,  Table_SVGA60_M_HALF,  Table_SVGA60_S0_SMALL,  Table_SVGA60_S0_MIDDLE,  Table_SVGA60_S0_LARGE,  Table_SVGA60_S0_POP,  Table_DTV2480I_S0_DUAL,Table_YUV480I_S1_DUAL},
	{Table_DTV2480I_M_FULL,Table_DTV2480I_M_HALF,Table_DTV2480I_S0_SMALL,Table_DTV2480I_S0_MIDDLE,Table_DTV2480I_S0_LARGE,Table_DTV2480I_S0_POP,Table_DTV2480I_S0_DUAL,Table_YUV480I_S1_DUAL},
	{Table_DTV2576I_M_FULL,Table_DTV2576I_M_HALF,Table_DTV2576I_S0_SMALL,Table_DTV2576I_S0_MIDDLE,Table_DTV2576I_S0_LARGE,Table_DTV2576I_S0_POP,Table_DTV2576I_S0_DUAL,Table_YUV480I_S1_DUAL}
};

#ifdef TW8823HANSTAR
BYTE VsyncDelay=0;
#endif

/*
CODE WORD Main_PIP0_MIX_Tbl[MAXINPORT] = {
	0x0001,
	0x0002,
	0x0004,
	0x0008,
	0x0010,
	0x0020,
	0x0040,
	0x0080,
	0x0100
};

CODE WORD Main_PIP1_MIX_Tbl[MAXINPORT] = {
	0x0001,
	0x0002,
	0x0004,
	0x0008,
	0x0010,
	0x0020,
	0x0040,
	0x0080,
	0x0100
};

CODE WORD PIP0_PIP1_MIX_Tbl[MAXINPORT] = {
	0x0001,
	0x0002,
	0x0004,
	0x0008,
	0x0010,
	0x0020,
	0x0040,
	0x0080,
	0x0100
};

#define IsAvailabe(MainInport, PIP0Inport, PIP1Inport) \
	(((Main_PIP0_MIX_Tbl[MainInport]>>PIP0Inport)&0x0001)| \
	(((Main_PIP1_MIX_Tbl[MainInport]>>PIP1Inport)&0x0001)<<1)| \
	(((PIP0_PIP1_MIX_Tbl[PIP0Inport]>>PIP1Inport)&0x0001)<<2))
*/

void TW8823ModeInit(void)
{
	//Printf("\nTW8823ModeInit...");
	I2CDeviceInitialize(Table_Inital);

	delay(100);  //Wait for the data signal being stable, then open the backlight
	WriteTW88(0xff, 0x0d);
	WriteTW88(0x03, ReadTW88(0x03)|0x80);

	return;
}

void TW8823InPortSet(INPORT inport)
{
	//Printf("\r\nTW8823InPortSet Input %bd", inport); 
	I2CDeviceInitialize(Table88_Inport[inport]);
	switch (inport){
	case ARGB_SOG:
	case CVBS_Y0:
	case CVBS_Y1:
	case CVBS_Y2:
	case CVBS_Y3:
	case YC_Y1C:
	case DTV1_RGB:
	case DTV2_BT656:
	case ARGB_HV:
	case EX_CVBS_Y0:
	case EX_YC_Y1:
	default:
		break;
	}
	
	return;
}

void TW8823OutPortSet(OUTPORT outport)
{
	//Printf("\r\TW8823OutPortSet Output %bd", outport); 
	I2CDeviceInitialize(Table88_Outport[outport]);
	switch (outport){
	case PIP0WIN:
	case PIP1WIN:
	case MAINWIN:
	default:
		break;
	}

	return;
}

void TW8823SigFmtSet(SIGFMT sigfmt)
{
	//Printf("\r\n TW8823SigFmtSet %bd", sigfmt);
	I2CDeviceInitialize(Table88_Sig_FMT[sigfmt]);
	switch (sigfmt){
	case NTSC:
	case PAL:
	case YUV480I:
	case YUV576I:
	case YUV480P:
	case YUV576P:
	case SVGA60:
	case DTV2480I:
	case DTV2576I:
	case NOTDET:
	default:
		break;
	}
	return;
}

void TW8823ModeSet(SIGFMT sigfmt, DISPMODE dispmode)
{
	//Printf("\r\nTW8823ModeSet Input|Disp mode %bd|%bd", sigfmt, dispmode); 
	//I2CDeviceInitialize(Table88_Scaler[sigfmt][dispmode]);
	I2CDeviceInitialize(Table88_Scaler[sigfmt][dispmode]);
	
	switch (dispmode){
	case FULL_800x480:
	case HALF_400x480:
		WriteTW88(0xff, 0x04);
		WriteTW88(0x00, ReadTW88(0x00)&0xfc);
		switch (sigfmt){
		case NTSC:
		case PAL:
			WriteTW88(0x00, ReadTW88(0x00)|0x00);
			break;
		case YUV480I:
		case YUV576I:
		case YUV480P:
		case YUV576P:
		case SVGA60:
			WriteTW88(0x00, ReadTW88(0x00)|0x01);
			break;
		case DTV2480I:
		case DTV2576I:
			WriteTW88(0x00, ReadTW88(0x00)|0x03);
			break;
		default:
			break;
		}
		break;
	case SMALL_400x240:
	case MIDDLE_600x400:
	case LARGE_800x480:
	case POP_400x480:
	case DUAL0_400x240:
		WriteTW88(0xff, 0x06);
		WriteTW88(0x71, ReadTW88(0x71)&0xf3);
		WriteTW88(0x15, ReadTW88(0x15)|0x40);
		switch (sigfmt){
		case NTSC:
		case PAL:
			WriteTW88(0x71, ReadTW88(0x71)|0x00);
			break;
		case YUV480I:
		case YUV576I:
		case YUV480P:
		case YUV576P:
		case SVGA60:
			WriteTW88(0x71, ReadTW88(0x71)|0x04);
			break;
		case DTV2480I:
		case DTV2576I:
			WriteTW88(0x71, ReadTW88(0x71)|0x0c);
			WriteTW88(0x16, ReadTW88(0x16)|0x08);
			break;
		default:
			break;
		}
		break;
	case DUAL1_400x240:
		WriteTW88(0xff, 0x06);
		WriteTW88(0x71, ReadTW88(0x71)&0xfc);
		WriteTW88(0x45, ReadTW88(0x45)|0x40);
		switch (sigfmt){
		case NTSC:
		case PAL:
			WriteTW88(0x71, ReadTW88(0x71)|0x00);
			break;
		case YUV480I:
		case YUV576I:
		case YUV480P:
		case YUV576P:
		case SVGA60:
			WriteTW88(0x71, ReadTW88(0x71)|0x01);
			break;
		case DTV2480I:
		case DTV2576I:
			WriteTW88(0x71, ReadTW88(0x71)|0x03);
			WriteTW88(0x46, ReadTW88(0x46)|0x08);
			break;
		default:
			break;
		}
		break;
	default:
		break;
	}


	//fix PIP YUV the pol of vsync need invert
	switch (dispmode){
	case SMALL_400x240:
	case MIDDLE_600x400:
	case LARGE_800x480:
	case POP_400x480:
	case DUAL0_400x240:
	case DUAL1_400x240:
		switch (sigfmt){
		case YUV480I:
		case YUV576I:
		case YUV480P:
		case YUV576P:
			WriteTW88(0xff, 0x02);
			WriteTW88(0xcc, ReadTW88(0xcc)|0x02);
			break;
		case NTSC:
		case PAL:
		case SVGA60:
		case DTV2480I:
		case DTV2576I:
		default:
			break;
		}
		break;
	case FULL_800x480:
	case HALF_400x480:
	default:
		break;
	}



	return;
}

SIGFMT TW8823SigFmtDetect(INPORT inport)
{
	BYTE std=NOTDET;
	WORD i;

	switch (inport){
	case CVBS_Y0:
	case CVBS_Y1:
	case CVBS_Y2:
	case CVBS_Y3:
	case YC_Y1C:
		WriteTW88(0xff, 0x01);
		if(ReadTW88(0x01) & 0x80){
			return NOTDET;
		}
		do{
			std = ReadTW88(0x1c);
		}while(std & 0x80);
		
		if(ReadTW88(0x01) & 0x80){
			return NOTDET;
		}
		
		std = (std&0x70)>>4;
		if(std == 0){
			std = NTSC;
			//Printf("\r\n DET NTSC");
		}else if(std == 1){
			std = PAL;
			//Printf("\r\n DET PAL");
		}else{
			std = NOTDET;
			//Printf("\r\n DET NOTDET");
		}
		break;
	case ARGB_SOG:
		WriteTW88(0xff, 0x02);
		
		i=0;
		do{
			std = ReadTW88(0xc1);
			i++;
			if((std&0x07)!=7){
				//Printf("\r\n ARGB_SOG %d", i);
				break;
			}
		}while(((std & 0x08)==0)&&(i<1000));
		
		if(std & 0x08){
		}else{
			return NOTDET;
		}

		std &= 0x07;
		if(std == 0){
			std = YUV480I;
			//Printf("\r\n DET YUV480I");
		}else if(std == 1){
			std = YUV576I;
			//Printf("\r\n DET YUV576I");
		}else if(std == 2){
			std = YUV480P;
			//Printf("\r\n DET YUV480P");
		}else if(std == 3){
			std = YUV576P;
			//Printf("\r\n DET YUV576P");
		}else{
			std = NOTDET;
			//Printf("\r\n DET NOTDET");
		}
		break;
	case EX_CVBS_Y0:
	case EX_YC_Y1:
	case DTV2_BT656:
		if(ReadI2C(0x8a, 0x01) & 0x80){
			return NOTDET;
		}
		do{
			std = ReadI2C(0x8a, 0x1c);
		}while(std & 0x80);

		std = (std&0x70)>>4;
		if(std == 0){
			std = DTV2480I;
			//Printf("\r\n DET DTV480I");
		}else if(std == 1){
			std = DTV2576I;
			//Printf("\r\n DET DTV576I");
		}else{
			std = NOTDET;
			//Printf("\r\n DET NOTDET");
		}
		break;
	case ARGB_HV:
		WriteTW88(0xff, 0x02);
		std = ReadTW88(0xc1);

		if((std&0x30)==0x30){
			std = SVGA60;
		}else{
			std = NOTDET;
		}
		break;
	case DTV1_RGB:
	default:
		std = NOTDET;
		//Printf("\r\n DET NOTDET");
		break;
	}

	return(std);
}

void TW8823OutPosSet(OUTPORT outport, WORD x, WORD y)
{
	//Printf("\r\n TW8823OutPosSet x|y %d|%d", x, y);

	#ifdef TW8823HANSTAR
	y += VsyncDelay;
	#endif
	
	WriteTW88(0xff, 0x06);
	switch (outport){
	case PIP0WIN:
		WriteTW88(0x1c, (ReadTW88(0x1c)&0xf0)|((BYTE)((x>>8)&0x0f)));
		WriteTW88(0x1d, (BYTE)x);
		WriteTW88(0x1e, (ReadTW88(0x1e)&0xf8)|((BYTE)((y>>8)&0x07)));
		WriteTW88(0x1f, (BYTE)y);
		break;
	case PIP1WIN:
		WriteTW88(0x4c, (ReadTW88(0x4c)&0xf0)|((BYTE)((x>>8)&0x0f)));
		WriteTW88(0x4d, (BYTE)x);
		WriteTW88(0x4e, (ReadTW88(0x4e)&0xf8)|((BYTE)((y>>8)&0x07)));
		WriteTW88(0x4f, (BYTE)y);
		break;
	case MAINWIN:
	default:
		break;
	}
	
	return;
}

void TW8823OutPortMute(OUTPORT outport, BOOL onoff) //TRUE: Mute(Blue) FALSE: Show Video
{
	//Printf("\r\n TW8823OutPortMute %bd",onoff);
	switch (outport){
	case MAINWIN:
		WriteTW88(0xff, 0x04);
		if(onoff){
			WriteTW88(0x70, ReadTW88(0x70)|0x02);
			WriteTW88(0x8A, ReadTW88(0x8A)|0x04);
		}else{
			WriteTW88(0x70, ReadTW88(0x70)&0xfd);
			WriteTW88(0x8A, ReadTW88(0x8A)&0xfb);
		}
		break;
	case PIP0WIN:
		WriteTW88(0xff, 0x06);
		if(onoff){
			WriteTW88(0x16, ReadTW88(0x16)|0x01);
		}else{
			WriteTW88(0x16, ReadTW88(0x16)&0xfe);
		}
		break;
	case PIP1WIN:
		WriteTW88(0xff, 0x06);
		if(onoff){
			WriteTW88(0x46, ReadTW88(0x46)|0x01);
		}else{
			WriteTW88(0x46, ReadTW88(0x46)&0xfe);
		}
		break;
	default:
		break;
	}

	//Fix
	#ifdef TW8823HANSTAR
	switch (outport){
	case MAINWIN:{
		WORD y;
		WriteTW88(0xff, 0x06);
		if(onoff){
			if(VsyncDelay == 0x13){
				y = ( ReadTW88( 0x1e ) << 8 ) + ReadTW88( 0x1f );
				y -= 0x13;
				WriteTW88(0x1e, (ReadTW88(0x1e)&0xf8)|((BYTE)((y>>8)&0x07)));
				WriteTW88(0x1f, (BYTE)y);

				y = ( ReadTW88( 0x4e ) << 8 ) + ReadTW88( 0x4f );
				y -= 0x13;
				WriteTW88(0x4e, (ReadTW88(0x4e)&0xf8)|((BYTE)((y>>8)&0x07)));
				WriteTW88(0x4f, (BYTE)y);
				VsyncDelay = 0;
			}
		}else{
			if(VsyncDelay == 0){

				y = ( ReadTW88( 0x1e ) << 8 ) + ReadTW88( 0x1f );
				y += 0x13;
				WriteTW88(0x1e, (ReadTW88(0x1e)&0xf8)|((BYTE)((y>>8)&0x07)));
				WriteTW88(0x1f, (BYTE)y);

				y = ( ReadTW88( 0x4e ) << 8 ) + ReadTW88( 0x4f );
				y += 0x13;
				WriteTW88(0x4e, (ReadTW88(0x4e)&0xf8)|((BYTE)((y>>8)&0x07)));
				WriteTW88(0x4f, (BYTE)y);
				VsyncDelay = 0x13;
			}
		}
		break;
	}
	case PIP0WIN:
	case PIP1WIN:
	default:
		break;
	}
	#endif

	return;
}


BOOL TW8823OutPortMuteDetect(OUTPORT outport)
{
	BOOL isMute = FALSE;
	
	switch (outport){
	case PIP0WIN:
		WriteTW88(0xff, 0x06);
		isMute = ((ReadTW88(0x16)&0x01)?TRUE:FALSE);
		break;
	case PIP1WIN:
		WriteTW88(0xff, 0x06);
		isMute = ((ReadTW88(0x46)&0x01)?TRUE:FALSE);
		break;
	case MAINWIN:
		WriteTW88(0xff, 0x04);
		isMute = ((ReadTW88(0x70)&0x02)?TRUE:FALSE);
		break;
	default:
		isMute = FALSE;
		break;
	}

	//Printf("\r\n TW8823OutPortMuteDetect %bd", isMute);
	return(isMute);
}

void TW8823OutPortEn(OUTPORT outport, BOOL onoff) //TRUE: Enable FALSE: Disable
{
	//Printf("\r\n TW8823OutPortEn %bd",onoff);
	switch (outport){
	case PIP0WIN:
		WriteTW88(0xff, 0x06);
		if(onoff){
			WriteTW88(0x16, ReadTW88(0x16)|0xa0);
		}else{
			WriteTW88(0x16, ReadTW88(0x16)&0x5f);
		}
		if(onoff){
			WriteTW88(0x15, ReadTW88(0x15)|0x80);
		}else{
			WriteTW88(0x15, ReadTW88(0x15)&0x7f);
		}
		break;
	case PIP1WIN:
		WriteTW88(0xff, 0x06);
		if(onoff){
			WriteTW88(0x46, ReadTW88(0x46)|0xa0);
		}else{
			WriteTW88(0x46, ReadTW88(0x46)&0x5f);
		}
		if(onoff){
			WriteTW88(0x45, ReadTW88(0x45)|0x80);
		}else{
			WriteTW88(0x45, ReadTW88(0x45)&0x7f);
		}
		break;
	case MAINWIN:
	default:
		break;
	}

	return;
}

